package com.dp.appi.controller;

import com.dp.appi.entity.UserEntity;
import com.dp.appi.exception.CommonException;
import com.dp.appi.service.ConsumerService;
import com.dp.appi.service.PayService;
import com.dp.appi.util.DateUtil;
import com.dp.appi.util.ExceptionUtil;
import com.dp.appi.util.SYS;
import com.dp.appi.util.StringUtil;
import com.dp.appi.util.alipay2.config.AlipayConfig;
import com.dp.appi.util.alipay2.sign.RSA;
import com.dp.appi.util.alipay2.util.AliUtil;
import com.dp.appi.util.alipay2.util.AlipayCore;
import com.dp.appi.util.alipay2.util.AlipayNotify;
import com.dp.appi.util.alipay2.util.UtilDate;
import com.dp.appi.util.wxpay.WxUtil;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by bchen on 2016/6/20.
 */
@Controller
@RequestMapping(value = "/payControl")
public class PayControl {
    private static Logger log = LoggerFactory.getLogger(PayControl.class);

    @Autowired
    private PayService payService;
    @Autowired
    private ConsumerService consumerService;

    @Value("${ali_notify_url}")
    private String ali_notify_url;
    @Value("${wx_notify_url}")
    private String wx_notify_url;

    /**
     * 购买产品
     * @param param
     */
    @RequestMapping(value = "/payment")
    public void payment(@RequestParam Map<String, String> param, HttpServletResponse response){
        String openIdent = param.get("openIdent");
        Gson gson = new Gson();
        PrintWriter out = null;
        try{
            out = response.getWriter();
            UserEntity userEntity = UserEntity.decrypt(openIdent);
            Map<String, Object> map = consumerService.getUser(userEntity);
            if(map != null){
                String id = map.get("id").toString();
                synchronized (id) { //同一个用户被锁住
                    String buy_menu_id = param.get("buy_menu_id"); //购买菜单id
                    String type = param.get("type"); //适用类别
                    Map<String, Object> buyMentMap = payService.getBuyMent(Long.valueOf(buy_menu_id), Integer.valueOf(type));
                    if(buyMentMap != null){
                        String payid = param.get("payid");
                        String outTradeNo = UtilDate.getOrderNum(); //订单号

                        String people_num = param.get("people_num"); //购买人数
                        String per_averages = buyMentMap.get("per_averages").toString(); //购买菜单的人均价
                        String products_price = buyMentMap.get("products_price").toString(); //购买菜单的产品价
                        BigDecimal totalFee_bd = new BigDecimal(people_num).multiply(new BigDecimal(per_averages)).add(new BigDecimal(products_price));

                        // buy_people为存表的购买人数，页面传来的人数+默认人数
                        int def_people = 0;
                        Object def_people_num = buyMentMap.get("def_people_num");
                        if(StringUtil.isNotEmpty(def_people_num)){
                            def_people = Integer.valueOf(def_people_num.toString());
                        }
                        int buy_people = Integer.valueOf(people_num) + def_people;

                        String atta_str = type + id + "ZZ" + buy_menu_id + "ZZ" + buy_people; //用ZZ分隔

                        String linkString = buildLink(payid, outTradeNo, "payment", totalFee_bd, atta_str);
                        out.print(linkString);
                    }else{
                        out.print(gson.toJson(SYS.BUY0001.msgMap()));
                    }
                }
            }else{
                out.print(gson.toJson(SYS.EXPO014.msgMap()));
            }
        }catch (Exception e){
            log.error(e.getMessage(), e);
            out.print(gson.toJson(SYS.E10002.msgMap()));
        }
    }

    @RequestMapping(value = "/aliNotifyUrl", method = RequestMethod.POST)
    public void aliNotifyUrl(HttpServletRequest request, HttpServletResponse response) {
        PrintWriter out = null;
        Map<String, String> params = AliUtil.getAliResult(request.getParameterMap());
        try {
            out = response.getWriter();

            String trade_status = params.get("trade_status");//交易状态
            String notify_id = params.get("notify_id");//异步通知ID
            String sign = params.get("sign");//签名

            ////判断接受的post通知中有无notify_id，如果有则是异步通知。
            if(notify_id != "" && notify_id != null) {
                //判断成功之后使用getResponse方法判断是否是支付宝发来的异步通知。
                if (AlipayNotify.verifyResponse(notify_id).equals("true")){
                    //使用支付宝公钥验签
                    if(AlipayNotify.getSignVeryfy(params, sign)) {
                        if (trade_status.equals("TRADE_SUCCESS") || trade_status.equals("TRADE_FINISHED")) { //交易成功，且可对该交易做操作
                            String out_trade_no = params.get("out_trade_no");//商户订单号
                            String gmt_payment = params.get("gmt_payment");//支付完成日期
                            String total_fee = params.get("total_fee");//支付金额

                            String[] ss = out_trade_no.split("ZZ");
                            String tradeNo_type_userId = ss[0];
                            String type = tradeNo_type_userId.substring(14, 15);//前面14位是 年月日时分秒 订单号
                            String user_id = tradeNo_type_userId.substring(15, tradeNo_type_userId.length());
                            String buy_menu_id = ss[1];//购买菜单id
                            String people_num = ss[2]; //购买人数

                            payService.buySuccess(user_id, total_fee, type, people_num, buy_menu_id, DateUtil.formatDateStr(gmt_payment, "yyyy-MM-dd"));

                            out.print("success");
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RequestMapping(value = "/wxNotifyUrl")
    public void wxNotifyUrl(HttpServletRequest request, HttpServletResponse response) {
        PrintWriter out = null;
        Map<String, String> xml = WxUtil.getWxResult(request);
        try {
            out = response.getWriter();

            String callbackParamSign = xml.get("callbackParamSign");
            String sign = xml.get("sign");

            if(!StringUtils.isEmpty(callbackParamSign) && !StringUtils.isEmpty(sign) && callbackParamSign.equals(sign)){
                //String out_trade_no = xml.get("out_trade_no");//商户订单号
                String attach = xml.get("attach");//附加项
                if ("SUCCESS".equals(xml.get("return_code")) && "SUCCESS".equals(xml.get("result_code"))) {
                    String time_end = xml.get("time_end");//支付完成日期
                    BigDecimal bg_money = new BigDecimal(xml.get("total_fee"));//交易金额
                    bg_money = bg_money.divide(new BigDecimal(100));//将分转换为元

                    String[] attachs = attach.split("ZZ");
                    String type_userId = attachs[0];//适用类别+用户id
                    String type = type_userId.substring(0, 1);
                    String user_id = type_userId.substring(1, type_userId.length());
                    String buy_menu_id = attachs[1];//购买菜单id
                    String people_num = attachs[2]; //购买人数

                    time_end = time_end.substring(0, 8);
                    String y = time_end.substring(0, 4);
                    String m = time_end.substring(4, 6);
                    String d = time_end.substring(6);
                    payService.buySuccess(user_id, String.valueOf(bg_money.doubleValue()), type, people_num, buy_menu_id, y + "-" + m + "-" + d);

                    out.print("success");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 平台产品购买清单
     * @param modelMap
     * @param param
     */
    @RequestMapping(value = "/buyMenuList",method = RequestMethod.GET)
    public void ptList(ModelMap modelMap, @RequestParam Map<String,String> param) {
        try {
            String appliesTypeStr = param.get("appliesType");
            Integer appliesType = StringUtil.isEmpty(appliesTypeStr)?null:Integer.parseInt(appliesTypeStr);
            modelMap.addAttribute("buyMenuList",payService.buyMenuList(appliesType));
        }catch (CommonException c) {
            modelMap.addAllAttributes(SYS.valueOf(c.getMessage()).msgMap());
        }catch (Exception e){
            modelMap.addAllAttributes(SYS.E10002.msgMap());
            log.error(ExceptionUtil.getExceptionAllinformation(e));
        }
    }

    /**
     * 构建支付连接
     */
    private String buildLink(String payid, String outTradeNo, String subject, BigDecimal bd, String atta_str) {
        String linkString = "";
        if ("ali".equals(payid)) {
            outTradeNo += atta_str; //第15位是适用类别，其它用ZZ分隔
            linkString = genAlipay(outTradeNo, bd.setScale(2, BigDecimal.ROUND_HALF_UP).toString(), subject);
        } else if ("wx".equals(payid)) {
            bd = bd.multiply(new BigDecimal(100));//将元转为分
            linkString = genWxpay("0.0.0.0", outTradeNo, String.valueOf(bd.setScale(2, BigDecimal.ROUND_HALF_UP).intValue()), subject, atta_str);
        }
        return linkString;
    }
    private String genAlipay(String outTradeNo, String money, String subject) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("partner", AlipayConfig.partner);
        map.put("seller_id", AlipayConfig.seller_email);
        map.put("out_trade_no", outTradeNo);
        map.put("subject", subject);
        map.put("body", subject);
        map.put("total_fee", money);
        map.put("notify_url", ali_notify_url);
        map.put("service", "mobile.securitypay.pay");
        map.put("payment_type", "1");
        map.put("_input_charset", AlipayConfig.input_charset);
        String str = AlipayCore.createLinkString(map);
        String mysign = RSA.sign(str, AlipayConfig.private_key, AlipayConfig.input_charset);
        String linkString = str;
        try {
            mysign = URLEncoder.encode(mysign, AlipayConfig.input_charset);
            linkString += "&sign=" + mysign + "&sign_type="+AlipayConfig.sign_type+"";
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> ali_result = new HashMap<>();
        ali_result.put("code", "SUCCESS");
        ali_result.put("data", linkString);
        String json_str = new Gson().toJson(ali_result);
        return json_str;
    }
    private String genWxpay(String remoteAddr, String outTradeNo, String money, String subject, String attach) {
        subject = "payment";
        Map<String, String> map = WxUtil.unifiedOrder(money, remoteAddr, outTradeNo, subject, wx_notify_url, attach);
        Map<String, Object> wx_result = new HashMap<>();
        wx_result.put("code", "SUCCESS");
        wx_result.put("data", map);
        String json_str = new Gson().toJson(wx_result);
        return json_str;
    }
}
